package com.sxj.corejava.code12_线程;

/**
 * @author 石小俊
 * @date 2025年02月24日
 */
public class Test05_线程安全问题 {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        Thread t1 = new Thread(ticket, "窗口1");
        Thread t2 = new Thread(ticket, "窗口2");
        Thread t3 = new Thread(ticket, "窗口3");
        t1.start();
        t2.start();
        t3.start();
        // 以最终出现了0号与-1号的情况为例,假设只剩下最后一张票
        // 当第一个线程拿到CPU时间片,开始执行代码,此时num=1
        // 在执行了num>0的判断之后,进入休眠状态
        // 这时候,其他两个线程是没有休眠的,正常执行
        // 第二个线程进来,执行判断,此时的num=1,满足条件,进入循环,进入循环之后休眠
        // 第三个线程进来,执行判断,此时的num=1,满足条件,进入循环,进入循环之后休眠
        // 这时候,第一个线程休眠结束,执行代码,出票1号票,此时的num--
        // 第二个线程休眠结束,由于已经进入循环了,因此不需要判断,直接出票,此时num的值为0,因此出票0号票,num--
        // 第三个线程休眠结束,由于已经进入循环了,因此不需要判断,直接出票,此时num的值为-1,因此出票-1号票
    }

}

class Ticket implements Runnable {
    // 共有100张票
    private static int num = 100;

    @Override
    public void run() {
        while (true) {
//            synchronized (this) {
//                if (num > 0) {
//                    try {
//                        Thread.sleep(10);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    System.out.println(Thread.currentThread().getName() + "正在出票,票号为:" + num--);
//                }
//            }
            sellTicket();
        }
    }

    public static synchronized void sellTicket() {
        if (num > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在出票,票号为:" + num--);
        }
    }

}